from fastapi import status, HTTPException, Depends, APIRouter, Form
from fastapi.security import OAuth2PasswordRequestForm
from models.core import UserOut, UserAuth, TokenSchema, SystemUser, RefreshToken
from services.utils import verify_password, get_hashed_password
from services.deps import get_current_user, deps_user_db, validate_refresh_token, jwt_auth_handler
from services.db import RedisUserSchema
from uuid import uuid4
from typing import Tuple

router = APIRouter()

@router.post('/signup', summary="Create new user", response_model=UserOut)
async def create_user(data: UserAuth, db:RedisUserSchema=Depends(deps_user_db)):
    isexists = await db.exists(data.email)
    if isexists:
            raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="User with this email already exist")
    user = {
        'email': data.email,
        'password': get_hashed_password(data.password),
        'id': str(uuid4())
    }
    await db.save(user)
    return user

@router.post('/login', summary="Create access and refresh tokens for user", response_model=TokenSchema)
async def login(form_data: OAuth2PasswordRequestForm = Depends(), db:RedisUserSchema=Depends(deps_user_db)):
    userDict = await db.get_by_email(form_data.username, defValue=None)
    if userDict is None:
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Incorrect email or password")

    hashed_pass = userDict['password']
    if not verify_password(form_data.password, hashed_pass):
        raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail="Incorrect email or password")

    return jwt_auth_handler.generate_passport(userDict['email'])

    
@router.get('/me', summary='Get details of currently logged in user', response_model=UserOut)
async def get_me(user: SystemUser = Depends(get_current_user)):
    return user

@router.post('/refresh', summary='Create access and refresh tokens for user', response_model=RefreshToken)
async def refresh_access_token(access_token:str=Form(...), tupleArg: Tuple[SystemUser, RedisUserSchema] = Depends(validate_refresh_token)):
    return await jwt_auth_handler.refresh_passport(access_token, tupleArg[0].email, tupleArg[1])